home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume16 / pcomm2 / part08 < prev    next >
Encoding:
Internet Message Format  |  1988-09-14  |  22.8 KB

  1. Path: bbn.com!rsalz
  2. From: rsalz@uunet.uu.net (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v16i013:  Modem communications package, Part08/08
  5. Message-ID: <1065@fig.bbn.com>
  6. Date: 13 Sep 88 16:46:50 GMT
  7. Lines: 963
  8. Approved: rsalz@uunet.UU.NET
  9.  
  10. Submitted-by: Emmet P Gray <fthood!egray>
  11. Posting-number: Volume 16, Issue 13
  12. Archive-name: pcomm2/part08
  13.  
  14. #! /bin/sh
  15. # This is a shell archive, meaning:
  16. # 1. Remove everything above the #! /bin/sh line.
  17. # 2. Save the resulting text in a file.
  18. # 3. Execute the file with /bin/sh (not csh) to create:
  19. #    x_send.c
  20. #    x_win.c
  21. #    xmodem.c
  22. export PATH; PATH=/bin:/usr/bin:$PATH
  23. echo shar: "extracting 'x_send.c'" '(11511 characters)'
  24. if test -f 'x_send.c'
  25. then
  26.     echo shar: "will not over-write existing file 'x_send.c'"
  27. else
  28. sed 's/^X//' << \SHAR_EOF > 'x_send.c'
  29. X/*
  30. X * Send a list of files using a version of Ward Christensen's file
  31. X * transfer protocol.  A non-zero return code means an error must be
  32. X * acknowledged by the user (a user generated abort returns a 0).
  33. X */
  34. X
  35. X#include <stdio.h>
  36. X#include <curses.h>
  37. X#include <sys/types.h>
  38. X#include <sys/stat.h>
  39. X#include "config.h"
  40. X#include "dial_dir.h"
  41. X#include "misc.h"
  42. X#include "xmodem.h"
  43. X
  44. Xstatic int tot_err, err_method;
  45. X
  46. Xint
  47. Xsend_xmodem(win, list, type, fast)
  48. XWINDOW *win;
  49. Xchar *list;
  50. Xint type, fast;
  51. X{
  52. X    extern char *protocol[];
  53. X    FILE *fp, *my_fopen();
  54. X    int i, block_size, file_count, secs, mins, hours, big_blocks;
  55. X    int small_blocks, err_count, got_it, num, is_batch, code;
  56. X    int max_block, default_err;
  57. X    long size, block, sent, xmit_size;
  58. X    char *file, *strtok(), *name, *strrchr();
  59. X    unsigned short crc, calc_crc();
  60. X    unsigned char buf[1029], blk, calc_sum();
  61. X    unsigned int packet, sleep();
  62. X    float performance, percent;
  63. X    struct stat stbuf;
  64. X                    /* which protocol? */
  65. X    switch (type) {
  66. X        case XMODEM:
  67. X            is_batch = 0;
  68. X            default_err = CRC_CHECKSUM;
  69. X            max_block = 128;
  70. X            performance = 1.36;
  71. X            break;
  72. X        case XMODEM_1k:
  73. X            is_batch = 0;
  74. X            default_err = CRC_CHECKSUM;
  75. X            max_block = 1024;
  76. X            performance = 1.09;
  77. X            break;
  78. X        case MODEM7:
  79. X            is_batch = 1;
  80. X            default_err = CHECKSUM;
  81. X            max_block = 128;
  82. X            performance = 1.36;
  83. X            break;
  84. X        case YMODEM:
  85. X            is_batch = 1;
  86. X            default_err = CRC;
  87. X            max_block = 1024;
  88. X            performance = 1.09;
  89. X            break;
  90. X        case YMODEM_G:
  91. X            is_batch = 1;
  92. X            default_err = NONE;
  93. X            max_block = 1024;
  94. X            performance = 1.02;
  95. X            break;
  96. X        default:
  97. X            return(1);
  98. X    }
  99. X
  100. X    tot_err = 0;
  101. X    file_count = 0;
  102. X    mvwaddstr(win, 2, 24, protocol[type]);
  103. X    mvwaddstr(win, 11, 24, "0  ");
  104. X
  105. X                    /* each one in the list */
  106. X    file = strtok(list, "     ");
  107. X    do {
  108. X                    /* is it a batch type? */
  109. X        file_count++;
  110. X        if (file_count > 1 && !is_batch)
  111. X            break;
  112. X                    /* display the name */
  113. X        clear_line(win, 3, 24, 1);
  114. X        if ((name = strrchr(file, '/')))
  115. X            name++;
  116. X        else
  117. X            name = file;
  118. X        waddstr(win, name);
  119. X        wrefresh(win);
  120. X                    /* get the file size */
  121. X        if (stat(file, &stbuf) < 0) {
  122. X            beep();
  123. X            clear_line(win, 12, 24, 1);
  124. X            wattrstr(win, A_BOLD, "CAN'T FIND FILE");
  125. X            wrefresh(win);
  126. X            sleep(3);
  127. X            continue;
  128. X        }
  129. X                    /* sanity checking */
  130. X        if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
  131. X            beep();
  132. X            clear_line(win, 12, 24, 1);
  133. X            wattrstr(win, A_BOLD, "NOT REGULAR FILE");
  134. X            wrefresh(win);
  135. X            sleep(3);
  136. X            continue;
  137. X        }
  138. X
  139. X        size = stbuf.st_size;
  140. X        mvwprintw(win, 4, 24, "%-10ld", size);
  141. X        clear_line(win, 5, 24, 1);
  142. X
  143. X        if (!(fp = my_fopen(file, "r"))) {
  144. X            beep();
  145. X            clear_line(win, 12, 24, 1);
  146. X            wattrstr(win, A_BOLD, "PERMISSION DENIED");
  147. X            wrefresh(win);
  148. X            sleep(3);
  149. X            continue;
  150. X        }
  151. X                    /* get the xmit size */
  152. X        block_size = max_block;
  153. X        big_blocks = 0;
  154. X        small_blocks = 0;
  155. X        if (block_size == 128) {
  156. X            small_blocks = size / 128;
  157. X            if (size % 128)
  158. X                small_blocks++;
  159. X        }
  160. X        else {
  161. X            big_blocks = size / 1024;
  162. X            small_blocks = (size % 1024) / 128;
  163. X            if (size % 128)
  164. X                small_blocks++;
  165. X
  166. X            if (small_blocks == 8 && !big_blocks) {
  167. X                big_blocks++;
  168. X                small_blocks = 0;
  169. X            }
  170. X                    /* if tiny file */
  171. X            if (big_blocks == 0)
  172. X                block_size = 128;
  173. X        }
  174. X
  175. X        xmit_size = ((unsigned int) big_blocks * 1024L) + ((unsigned int) small_blocks * 128L);
  176. X                    /* add block 0 to the size */
  177. X        if (type == YMODEM || type == YMODEM_G)
  178. X            xmit_size += 128L;
  179. X
  180. X        secs = (xmit_size * 10.0 / dir->baud[dir->d_cur]) * performance;
  181. X        hours = secs / 3600;
  182. X        mins = (secs % 3600) / 60;
  183. X        secs = (secs % 3600) % 60;
  184. X
  185. X        mvwprintw(win, 6, 24, "%d:%02d:%02d", hours, mins, secs);
  186. X
  187. X                    /* some starting numbers */
  188. X        mvwaddstr(win, 7, 24, "     ");
  189. X        mvwaddstr(win, 8, 24, "0%  ");
  190. X        mvwaddstr(win, 9, 24, "0          ");
  191. X        mvwaddstr(win, 10, 24, "0 ");
  192. X        clear_line(win, 12, 24, 1);
  193. X        waddstr(win, "NONE");
  194. X        wrefresh(win);
  195. X                    /* send the batch stuff */
  196. X        switch (type) {
  197. X            case MODEM7:
  198. X                if (code = rcv_first(win, default_err)) {
  199. X                    fclose(fp);
  200. X                    return(code +1);
  201. X                }
  202. X
  203. X                if (send_modem7(win, name)) {
  204. X                    fclose(fp);
  205. X                    return(1);
  206. X                }
  207. X                break;
  208. X            case YMODEM:
  209. X            case YMODEM_G:
  210. X                if (code = rcv_first(win, default_err)) {
  211. X                    fclose(fp);
  212. X                    return(code +1);
  213. X                }
  214. X
  215. X                if (code = send_ymodem(win, name, size)) {
  216. X                    fclose(fp);
  217. X                    /*
  218. X                     * CANCEL now means that the other
  219. X                     * end can't open that file.
  220. X                     */
  221. X                    if (code == CANCEL)
  222. X                        break;
  223. X                    return(code +1);
  224. X                }
  225. X                xmit_size -= 128L;
  226. X                break;
  227. X            default:
  228. X                code = 0;
  229. X                break;
  230. X        }
  231. X                    /* remote can't receive that file? */
  232. X        if (code == CANCEL)
  233. X            break;
  234. X                    /* wait for first character */
  235. X        if (code = rcv_first(win, default_err)) {
  236. X            fclose(fp);
  237. X            return(code +1);
  238. X        }
  239. X                    /* here we go... */
  240. X        clear_line(win, 12, 24, 1);
  241. X        waddstr(win, "NONE");
  242. X        wrefresh(win);
  243. X        sent = 0L;
  244. X        block = 1L;
  245. X        blk = 1;
  246. X        while (num = fread((char *) &buf[3], sizeof(char), block_size, fp)) {
  247. X
  248. X                    /* fill short block */
  249. X            if (num < block_size) {
  250. X                for (i=num; i<block_size; i++)
  251. X                    buf[i+3] = CTRLZ;
  252. X            }
  253. X
  254. X                    /* show current stats */
  255. X            mvwprintw(win, 7, 24, "%-5ld", block);
  256. X            if (fast) {
  257. X                percent = sent * 100.0 / xmit_size;
  258. X                mvwprintw(win, 8, 24, "%0.1f%%", percent);
  259. X                mvwprintw(win, 9, 24, "%-10ld", sent);
  260. X            }
  261. X            wrefresh(win);
  262. X
  263. X                    /* build the header */
  264. X            if (block_size == 128)
  265. X                buf[0] = SOH;
  266. X            else
  267. X                buf[0] = STX;
  268. X
  269. X            buf[1] = blk;
  270. X            buf[2] = ~blk;
  271. X
  272. X                    /* build the error detection stuff */
  273. X            switch (err_method) {
  274. X                case CHECKSUM:
  275. X                    buf[block_size+3] = calc_sum(&buf[3], block_size);
  276. X#ifdef DEBUG
  277. X                    fprintf(stderr, "blk=%d, checksum=%d\n", blk, buf[block_size+3]);
  278. X#endif /* DEBUG */
  279. X                    packet = block_size +4;
  280. X                    break;
  281. X                case CRC:
  282. X                    crc = calc_crc(&buf[3], block_size);
  283. X                    buf[block_size+3] = crc >> 8;
  284. X                    buf[block_size+4] = crc;
  285. X#ifdef DEBUG
  286. X                    fprintf(stderr, "blk=%d, crc1=%d, crc2=%d\n", blk, buf[block_size+3], buf[block_size+4]);
  287. X#endif /* DEBUG */
  288. X                    packet = block_size +5;
  289. X                    break;
  290. X                case NONE:
  291. X                    buf[block_size+3] = 0;
  292. X                    buf[block_size+4] = 0;
  293. X                    packet = block_size +5;
  294. X                    break;
  295. X            }
  296. X
  297. X                    /* send the block */
  298. X            if (code = send_block(win, buf, packet)) {
  299. X                fclose(fp);
  300. X                return(code +1);
  301. X            }
  302. X            block++;
  303. X            blk++;
  304. X            sent = sent + (unsigned int) block_size;
  305. X
  306. X                    /* change block size? */
  307. X            if (xmit_size - sent < 1024)
  308. X                block_size = 128;
  309. X        }
  310. X        mvwaddstr(win, 8, 24, "100%  ");
  311. X        mvwprintw(win, 9, 24, "%-10ld", sent);
  312. X                    /* at the end of the file */
  313. X        err_count = 0;
  314. X        got_it = 0;
  315. X        while (err_count < MAX_ERRORS) {
  316. X            putc_line(EOT);
  317. X            if (getc_line(10) == ACK) {
  318. X                got_it++;
  319. X                break;
  320. X            }
  321. X            err_count++;
  322. X        }
  323. X        clear_line(win, 12, 24, 1);
  324. X        if (!got_it) {
  325. X            /*
  326. X             * So what???  We don't do anything if there is
  327. X             * no acknowledge from the host!!
  328. X             */
  329. X            waddstr(win, "NO ACKNOWLEDGE");
  330. X        }
  331. X        else
  332. X            waddstr(win, "TRANSFER COMPLETE");
  333. X        if (!is_batch)
  334. X            beep();
  335. X        wrefresh(win);
  336. X        sleep(2);
  337. X                    /* prepare to start again */
  338. X        fclose(fp);
  339. X    } while (file = strtok((char *) NULL, "     "));
  340. X
  341. X    /*
  342. X     * The end of batch markers... For modem7 it's an ACK and EOT, for
  343. X     * ymodem, it's an empty block 0.
  344. X     */
  345. X    switch (type) {
  346. X        case MODEM7:
  347. X            if (code = rcv_first(win, default_err))
  348. X                return(code +1);
  349. X            putc_line(ACK);
  350. X            putc_line(EOT);
  351. X            beep();
  352. X            wrefresh(win);
  353. X            break;
  354. X        case YMODEM:
  355. X        case YMODEM_G:
  356. X            if (code = rcv_first(win, default_err))
  357. X                return(code +1);
  358. X
  359. X            if (code = send_ymodem(win, "", 0L))
  360. X                return(code +1);
  361. X            beep();
  362. X            wrefresh(win);
  363. X            break;
  364. X        default:
  365. X            break;
  366. X    }
  367. X    return(0);
  368. X}
  369. X
  370. X/*
  371. X * Wait for the first character to start the transmission.  This first
  372. X * character also sets the crc/checksum method.  Returns the standard
  373. X * error codes, or 0 on success.  The variable err_method is global.
  374. X */
  375. X
  376. Xstatic int
  377. Xrcv_first(win, default_err)
  378. XWINDOW *win;
  379. Xint default_err;
  380. X{
  381. X    int i, err_count;
  382. X    unsigned int sleep();
  383. X    void cancel_xfer();
  384. X
  385. X    err_count = 0;
  386. X    while (err_count < MAX_ERRORS) {
  387. X
  388. X                    /* scan the keyboard for abort */
  389. X        if (wgetch(win) == ESC) {
  390. X            beep();
  391. X            clear_line(win, 12, 24, 1);
  392. X            waddstr(win, "ABORTED");
  393. X            wrefresh(win);
  394. X            cancel_xfer(0);
  395. X            sleep(3);
  396. X            return(ABORT);
  397. X        }
  398. X                    /* scan the TTY line */
  399. X        i = getc_line(10);
  400. X#ifdef DEBUG
  401. X        fprintf(stderr, "rcv_first: got '%c', %02x, %03o, %d\n", i, i, i, i);
  402. X#endif /* DEBUG */
  403. X        switch (i) {
  404. X            case -1:    /* timed out */
  405. X                clear_line(win, 12, 24, 1);
  406. X                wattrstr(win, A_BOLD, "NO RESPONSE");
  407. X                err_count++;
  408. X                break;
  409. X            case NAK:    /* checksum marker */
  410. X                if (default_err == CHECKSUM || default_err == CRC_CHECKSUM) {
  411. X                    mvwaddstr(win, 5, 24, "CHECKSUM");
  412. X                    err_method = CHECKSUM;
  413. X                    return(0);
  414. X                }
  415. X                err_count++;
  416. X                break;
  417. X            case 'C':    /* CRC marker */
  418. X                if (default_err == CRC_CHECKSUM || default_err == CRC) {
  419. X                    mvwaddstr(win, 5, 24, "CRC");
  420. X                    err_method = CRC;
  421. X                    return(0);
  422. X                }
  423. X                err_count++;
  424. X                break;
  425. X            case 'G':    /* ymodem-g marker */
  426. X                if (default_err == NONE) {
  427. X                    mvwaddstr(win, 5, 24, "NONE");
  428. X                    err_method = NONE;
  429. X                    return(0);
  430. X                }
  431. X                err_count++;
  432. X                break;
  433. X            case CAN:    /* two CAN's and you're out! */
  434. X                if (getc_line(2) == CAN) {
  435. X                    beep();
  436. X                    clear_line(win, 12, 24, 1);
  437. X                    wattrstr(win, A_BOLD, "REMOTE ABORTED");
  438. X                    wrefresh(win);
  439. X                    return(CANCEL);
  440. X                }
  441. X                err_count++;
  442. X                break;
  443. X            default:
  444. X                clear_line(win, 12, 24, 1);
  445. X                waddstr(win, "BAD HEADER");
  446. X                err_count++;
  447. X                break;
  448. X        }
  449. X        mvwprintw(win, 10, 24, "%-2d", err_count);
  450. X        wrefresh(win);
  451. X    }
  452. X                    /* failed to get it right? */
  453. X    beep();
  454. X    clear_line(win, 12, 24, 1);
  455. X    wattrstr(win, A_BOLD, "TIMED OUT");
  456. X    wrefresh(win);
  457. X    return(ERROR);
  458. X}
  459. X
  460. X/*
  461. X * Send a block of data, scan the keyboard for a user abort, and check
  462. X * the return codes from the host.  Returns standard error codes or 0
  463. X * on success.
  464. X */
  465. X
  466. Xint
  467. Xsend_block(win, blk, packet)
  468. XWINDOW *win;
  469. Xunsigned char *blk;
  470. Xunsigned int packet;
  471. X{
  472. X    extern int fd;
  473. X    int i, err_count;
  474. X    void cancel_xfer();
  475. X
  476. X    err_count = 0;
  477. X    mvwaddstr(win, 10, 24, "0 ");
  478. X
  479. X    while (err_count < MAX_ERRORS) {
  480. X                    /* write the block */
  481. X        write(fd, (char *) blk, packet);
  482. X                    /* scan the keyboard */
  483. X        if (wgetch(win) == ESC) {
  484. X            beep();
  485. X            clear_line(win, 12, 24, 1);
  486. X            waddstr(win, "ABORTED");
  487. X            wrefresh(win);
  488. X            cancel_xfer(0);
  489. X            sleep(3);
  490. X            return(ABORT);
  491. X        }
  492. X                    /* ymodem-g doesn't need ACKs */
  493. X        if (err_method == NONE)
  494. X            return(0);
  495. X                    /* wait for acknowledge */
  496. X        i = getc_line(10);
  497. X#ifdef DEBUG
  498. X        fprintf(stderr, "send_block: got '%c', %02x, %03o, %d\n", i, i, i, i);
  499. X#endif /* DEBUG */
  500. X        switch (i) {
  501. X            case -1:    /* timed out */
  502. X                clear_line(win, 12, 24, 1);
  503. X                waddstr(win, "NO RESPONSE");
  504. X                err_count++;
  505. X                tot_err++;
  506. X                break;
  507. X            case ACK:    /* Hooray!! we got it */
  508. X                return(0);
  509. X            case NAK:    /* show our disappointment... */
  510. X                clear_line(win, 12, 24, 1);
  511. X                if (err_method == CRC)
  512. X                    waddstr(win, "CRC FAILED");
  513. X                else
  514. X                    waddstr(win, "CHECKSUM FAILED");
  515. X                err_count++;
  516. X                tot_err++;
  517. X                break;
  518. X            case CAN:    /* two CAN's and you're out! */
  519. X                if (getc_line(2) == CAN) {
  520. X                    beep();
  521. X                    clear_line(win, 12, 24, 1);
  522. X                    wattrstr(win, A_BOLD, "REMOTE ABORTED");
  523. X                    wrefresh(win);
  524. X                    return(CANCEL);
  525. X                }
  526. X                /* fall thru... */
  527. X            default:
  528. X                clear_line(win, 12, 24, 1);
  529. X                waddstr(win, "RESENDING");
  530. X                err_count++;
  531. X                tot_err++;
  532. X                break;
  533. X        }
  534. X        mvwprintw(win, 10, 24, "%-2d", err_count);
  535. X        mvwprintw(win, 11, 24, "%-3d", tot_err);
  536. X        wrefresh(win);
  537. X    }
  538. X                    /* failed to get it right */
  539. X    beep();
  540. X    clear_line(win, 12, 24, 1);
  541. X    wattrstr(win, A_BOLD, "TOO MANY ERRORS");
  542. X    wrefresh(win);
  543. X    cancel_xfer(0);
  544. X    return(ERROR);
  545. X}
  546. SHAR_EOF
  547. if test 11511 -ne "`wc -c < 'x_send.c'`"
  548. then
  549.     echo shar: "error transmitting 'x_send.c'" '(should have been 11511 characters)'
  550. fi
  551. fi
  552. echo shar: "extracting 'x_win.c'" '(2577 characters)'
  553. if test -f 'x_win.c'
  554. then
  555.     echo shar: "will not over-write existing file 'x_win.c'"
  556. else
  557. sed 's/^X//' << \SHAR_EOF > 'x_win.c'
  558. X/*
  559. X * Display the file transfer window, and invoke the transfer protocol.
  560. X */
  561. X
  562. X#include <stdio.h>
  563. X#include <curses.h>
  564. X#include "config.h"
  565. X#ifdef OLDCURSES
  566. X#include <termio.h>
  567. X#endif /* OLDCURSES */
  568. X#include "dial_dir.h"
  569. X#include "misc.h"
  570. X#include "xmodem.h"
  571. X
  572. Xvoid
  573. Xxfer_win(list, up, type)
  574. Xchar *list;
  575. Xint up, type;
  576. X{
  577. X    extern int fd;
  578. X    WINDOW *xf_win, *newwin();
  579. X    int ret_code, fast, my_speed;
  580. X    void xmodem_mode(), input_off(), line_set(), error_win(), st_line();
  581. X    static int speed[15] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
  582. X    1200, 1800, 2400, 4800, 9600, 19200};
  583. X    struct termio tbuf;
  584. X
  585. X    touchwin(stdscr);
  586. X    refresh();
  587. X    st_line("");
  588. X
  589. X    xf_win = newwin(15, 44, 2, 30);
  590. X    /*
  591. X     * This window should be in the non-blocking mode, so we can
  592. X     * scan the keyboard for input while transferring a file.
  593. X     */
  594. X    nodelay(xf_win, 1);
  595. X                    /* basic window stuff */
  596. X    mvwaddstr(xf_win, 2, 14, "Protocol:");
  597. X    mvwaddstr(xf_win, 3, 13, "File name:");
  598. X    mvwaddstr(xf_win, 4, 13, "File size:");
  599. X    mvwaddstr(xf_win, 5, 4, "Error check method:");
  600. X    mvwaddstr(xf_win, 6, 5, "Est transfer time:");
  601. X    mvwaddstr(xf_win, 7, 11, "Block count:");
  602. X    mvwaddstr(xf_win, 8, 6, "Percent complete:");
  603. X    mvwaddstr(xf_win, 9, 5, "Bytes transferred:");
  604. X    mvwaddstr(xf_win, 10, 5, "Errors this block:");
  605. X    mvwaddstr(xf_win, 11, 5, "Total error count:");
  606. X    mvwaddstr(xf_win, 12, 10, "Last message: NONE");
  607. X    box(xf_win, VERT, HORZ);
  608. X
  609. X    if (up)
  610. X        mvwattrstr(xf_win, 0, 17, A_BOLD, " Uploading ");
  611. X    else
  612. X        mvwattrstr(xf_win, 0, 16, A_BOLD, " Downloading ");
  613. X    mvwaddstr(xf_win, 14, 11, " Press <ESC> to abort ");
  614. X    wrefresh(xf_win);
  615. X                    /* fix up the terminal mode */
  616. X    input_off();
  617. X    xmodem_mode(fd);
  618. X
  619. X    /*
  620. X     * Is your terminal slower than the xfer baud rate?  For example:
  621. X     * I'm at home with my PC and 1200 baud modem, I call my system
  622. X     * at work so I can use their 2400 baud modems to call some other
  623. X     * system.  In this case, I don't wanna spend too much time updating
  624. X     * my screen at 1200 baud, when I'm transferring the file at 2400 baud.
  625. X     */
  626. X    fast = 0;
  627. X
  628. X    ioctl(0, TCGETA, &tbuf);
  629. X    my_speed = speed[tbuf.c_cflag & CBAUD];
  630. X
  631. X    if (my_speed >= dir->baud[dir->d_cur])
  632. X        fast++;
  633. X
  634. X    if (up)
  635. X        ret_code = send_xmodem(xf_win, list, type, fast);
  636. X    else
  637. X        ret_code = rcv_xmodem(xf_win, list, type, fast);
  638. X
  639. X    nodelay(xf_win, 0);
  640. X                    /* prompt for a key on errors */
  641. X    if (ret_code) {
  642. X        beep();
  643. X        clear_line(xf_win, 13, 9, 1);
  644. X        wattrstr(xf_win, A_BOLD, "Press any key to continue");
  645. X        wrefresh(xf_win);
  646. X        wgetch(xf_win);
  647. X    }
  648. X    werase(xf_win);
  649. X    wrefresh(xf_win);
  650. X    delwin(xf_win);
  651. X                    /* undo what xmodem_mode() did */
  652. X    line_set();
  653. X    return;
  654. X}
  655. SHAR_EOF
  656. if test 2577 -ne "`wc -c < 'x_win.c'`"
  657. then
  658.     echo shar: "error transmitting 'x_win.c'" '(should have been 2577 characters)'
  659. fi
  660. fi
  661. echo shar: "extracting 'xmodem.c'" '(6652 characters)'
  662. if test -f 'xmodem.c'
  663. then
  664.     echo shar: "will not over-write existing file 'xmodem.c'"
  665. else
  666. sed 's/^X//' << \SHAR_EOF > 'xmodem.c'
  667. X/*
  668. X * Miscellaneous routines to support the xmodem file transfer protocols.
  669. X */
  670. X
  671. X#define CLIST 64
  672. X
  673. X#include <stdio.h>
  674. X#include <signal.h>
  675. X#include <termio.h>
  676. X#include <sys/types.h>
  677. X#include <sys/stat.h>
  678. X#include "config.h"
  679. X#include "misc.h"
  680. X#include "param.h"
  681. X#include "xmodem.h"
  682. X
  683. X/*
  684. X * Calculate the CRC for the given buffer
  685. X */
  686. X
  687. Xunsigned short
  688. Xcalc_crc(buf, len)
  689. Xunsigned char *buf;
  690. Xint len;
  691. X{
  692. X    register int i;
  693. X    unsigned short crc;
  694. X    static unsigned short crctab[256] = {
  695. X    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
  696. X    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
  697. X    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
  698. X    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
  699. X    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
  700. X    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
  701. X    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
  702. X    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
  703. X    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
  704. X    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
  705. X    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
  706. X    0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
  707. X    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
  708. X    0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
  709. X    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
  710. X    0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
  711. X    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
  712. X    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
  713. X    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
  714. X    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
  715. X    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
  716. X    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  717. X    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
  718. X    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
  719. X    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
  720. X    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
  721. X    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
  722. X    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
  723. X    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
  724. X    0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
  725. X    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
  726. X    0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};
  727. X
  728. X    crc = 0;
  729. X    for (i=0; i<len; i++)
  730. X        crc = (crc<<8) ^ crctab[(crc>>8) ^ *buf++];
  731. X
  732. X    return(crc);
  733. X}
  734. X
  735. X/*
  736. X * Calculate the checksum for the given buffer.
  737. X */
  738. X
  739. Xunsigned char
  740. Xcalc_sum(buf, len)
  741. Xunsigned char *buf;
  742. Xint len;
  743. X{
  744. X    unsigned char sum;
  745. X
  746. X    sum = 0;
  747. X    while (--len >= 0)
  748. X        sum += *buf++;
  749. X
  750. X    return(sum);
  751. X}
  752. X
  753. X/*
  754. X * Get a single character from the line with a specified time-out period
  755. X * in seconds.  If the function times-out, it returns a -1.
  756. X */
  757. X
  758. Xstatic int gl_flag;
  759. X
  760. Xint
  761. Xgetc_line(sec)
  762. Xunsigned int sec;
  763. X{
  764. X    extern int fd;
  765. X    int gl_force();
  766. X    char c;
  767. X    unsigned int alarm();
  768. X
  769. X    signal(SIGALRM, gl_force);
  770. X    gl_flag = 0;
  771. X
  772. X    alarm(sec);
  773. X    if (read(fd, &c, 1) <= 0) {
  774. X        alarm(0);
  775. X        return(-1);
  776. X    }
  777. X    if (gl_flag)
  778. X        return(-1);
  779. X    alarm(0);
  780. X    return(c & 0xff);
  781. X}
  782. X/*ARGSUSED*/
  783. Xstatic int
  784. Xgl_force(dummy)
  785. Xint dummy;
  786. X{
  787. X    gl_flag = 1;
  788. X}
  789. X
  790. X/*
  791. X * Same as above, but reads a bunch of characters.  The return code is
  792. X * now just a success/fail indicator.
  793. X */
  794. X
  795. Xstatic int rl_flag;
  796. X
  797. Xint
  798. Xfread_line(buf, len, sec)
  799. Xunsigned char *buf;
  800. Xunsigned int len, sec;
  801. X{
  802. X    extern int fd;
  803. X    int n, rl_force();
  804. X    unsigned int try, alarm();
  805. X
  806. X    signal(SIGALRM, rl_force);
  807. X    rl_flag = 0;
  808. X
  809. X    alarm(sec);
  810. X    while (len) {
  811. X                    /* read at most CLIST characters */
  812. X        try = (len > CLIST) ? CLIST : len;
  813. X        if ((n = read(fd, (char *) buf, try)) <= 0) {
  814. X            alarm(0);
  815. X            return(-1);
  816. X        }
  817. X        if (rl_flag)
  818. X            return(-1);
  819. X        len -= n;
  820. X        buf = buf + n;
  821. X    }
  822. X    alarm(0);
  823. X    return(0);
  824. X}
  825. X/*ARGSUSED*/
  826. Xstatic int
  827. Xrl_force(dummy)
  828. Xint dummy;
  829. X{
  830. X    rl_flag = 1;
  831. X}
  832. X
  833. X/*
  834. X * Put a character on the TTY line.  This serves no useful purpose other
  835. X * than making the code look pretty.
  836. X */
  837. X
  838. Xint
  839. Xputc_line(c)
  840. Xunsigned char c;
  841. X{
  842. X    extern int fd;
  843. X
  844. X    return(write(fd, (char *) &c, 1));
  845. X}
  846. X
  847. X/*
  848. X * Put the TTY driver in the mode suitable for xmodem transfers.
  849. X */
  850. X
  851. Xvoid
  852. Xxmodem_mode(filedes)
  853. Xint filedes;
  854. X{
  855. X    struct termio tbuf;
  856. X
  857. X    ioctl(filedes, TCGETA, &tbuf);
  858. X    /*
  859. X     * Turn off the XON/XOFF flow control, turn off echoing, and
  860. X     * switch to 8 bit no parity.
  861. X     */
  862. X    tbuf.c_cc[4] = 1;        /* VMIN */
  863. X    tbuf.c_cc[5] = 0;        /* VTIME */
  864. X    tbuf.c_iflag = 0;        /* no flow control or mapping */
  865. X    tbuf.c_oflag = 0;        /* no char mapping or delays */
  866. X    tbuf.c_lflag = 0;        /* no echo or signals */
  867. X    tbuf.c_cflag &= ~PARENB;    /* no parity */
  868. X    tbuf.c_cflag &= ~CSIZE;
  869. X    tbuf.c_cflag |= CS8;        /* 8 bit */
  870. X
  871. X    ioctl(filedes, TCSETA, &tbuf);
  872. X    ioctl(filedes, TCFLSH, 2);
  873. X    return;
  874. X}
  875. X
  876. X/*
  877. X * Cancel the file transfer.  Send several ^X's to the remote, followed
  878. X * by an equal number of backspaces (in case they have already aborted and
  879. X * we're really at the command line).
  880. X */
  881. X
  882. Xvoid
  883. Xcancel_xfer(recv)
  884. Xint recv;
  885. X{
  886. X    extern char file_name[15];
  887. X
  888. X    if (recv && !strcmp(param->abort, "DELETE"))
  889. X        unlink(file_name);
  890. X
  891. X    putc_line(CAN);
  892. X    putc_line(CAN);
  893. X    putc_line(CAN);
  894. X    putc_line(BS);
  895. X    putc_line(BS);
  896. X    putc_line(BS);
  897. X    return;
  898. X}
  899. X
  900. X/*
  901. X * Shorten a file to a predetermined length.  Used to remove the ^Z
  902. X * padding from the end of files.  (Heaven help us, if one day a binary
  903. X * file actually has ^Z's as part of the end of the file).
  904. X */
  905. X
  906. Xint
  907. Xfix_length(file, len)
  908. Xchar *file;
  909. Xlong len;
  910. X{
  911. X    FILE *fp, *tempfp, *my_fopen();
  912. X    register int num;
  913. X    char *tempfile, *mktemp(), buf[BUFSIZ];
  914. X    struct stat stbuf;
  915. X
  916. X    if (stat(file, &stbuf) < 0)
  917. X        return(1);
  918. X                    /* see if we have any work to do */
  919. X    if (len >= stbuf.st_size)
  920. X        return(0);
  921. X
  922. X    if (!(fp = my_fopen(file, "r")))
  923. X        return(1);
  924. X
  925. X    /*
  926. X     * The temporary file should be in the same directory as the
  927. X     * file being received because otherwise we'd have no way of
  928. X     * guaranteeing they would be in the same file system.  (Hard
  929. X     * links across different file systems aren't allowed).
  930. X     */
  931. X    tempfile = mktemp("trunXXXXXX");
  932. X    if (!(tempfp = my_fopen(tempfile, "w"))) {
  933. X        fclose(fp);
  934. X        return(1);
  935. X    }
  936. X
  937. X    while (len != 0L) {
  938. X        num = (len > BUFSIZ) ? BUFSIZ : len;
  939. X        fread(buf, sizeof(char), num, fp);
  940. X        if (fwrite(buf, sizeof(char), num, tempfp) != num) {
  941. X            fclose(fp);
  942. X            fclose(tempfp);
  943. X            return(1);
  944. X        }
  945. X        len = len - (unsigned int) num;
  946. X    }
  947. X
  948. X    fclose(fp);
  949. X    fclose(tempfp);
  950. X
  951. X    if (unlink(file) < 0)
  952. X        return(1);
  953. X
  954. X    if (link(tempfile, file) < 0)
  955. X        return(1);
  956. X
  957. X    if (unlink(tempfile) < 0)
  958. X        return(1);
  959. X
  960. X    return(0);
  961. X}
  962. SHAR_EOF
  963. if test 6652 -ne "`wc -c < 'xmodem.c'`"
  964. then
  965.     echo shar: "error transmitting 'xmodem.c'" '(should have been 6652 characters)'
  966. fi
  967. fi
  968. exit 0
  969. #    End of shell archive
  970.  
  971. -- 
  972. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  973.